<?php
/**
 * @package qBase
 * @subpackage model
 *
 */

/**
 * Represents an QData object
 * 
 * @package qBase
 * @subpackage model
 */
class QData extends QObject implements QIData 
{
	/**
	 * The list of storage properties for all the classes that extend QData
	 * We are doing this for performance considerations
	 * The pattern is : $StorageProperties[class_name] = array('property_1', 'property_2', ...);
	 *
	 * @var array
	 */
	protected static $StorageProperties = array();
	/**
	 * The storage of the object
	 *
	 * @var QStorage
	 */
	private $_storage;
	/**
	 * The storage id of the object
	 *
	 * @var QStorageId
	 */
	private $_storage_id;
	/**
	 * The constructor
	 *
	 * @param QStorage $storage
	 * @param QStorageId $storage_id
	 */
	public function __construct(QStorage $storage = null, QStorageId $storage_id = null)
	{
		parent::__construct();

		if ($storage) $this->_storage = $storage;
		if ($storage_id) $this->_storage_id = $storage_id;
	}
	/**
	 * Gets the storage that this object should work with
	 *
	 * @return QStorage
	 */
	public function getStorage()
	{
		return $this->_storage;
	}
	/**
	 * Sets the storage that this object should work with
	 *
	 * @param QStorage $storage
	 */
	public function setStorage(QStorage $storage)
	{
		$this->_storage = $storage;
	}
	/**
	 * Gets the storage id if any was set
	 *
	 * @return QStorageId
	 */
	public function getStorageId()
	{
		return $this->_storage_id;
	}
	/**
	 * Sets the storage id for the object
	 *
	 * @param QStorageId $id
	 */
	public function setStorageId(QStorageId $id)
	{
		$this->_storage_id = $id;
	}
	/**
	 * Unsets the storage id if any
	 *
	 * @return boolean Returns true if a storage id existed
	 */
	public function unsetStorageId()
	{
		unset($this->_storage_id);
	}
	/**
	 * Gets the list of properties that will interact with the storage
	 *
	 * @return array Array of string
	 */
	public function getStorageProperties()
	{
		if (!isset(self::$StorageProperties[$this->getClassName()]))
		{
			$info = new ReflectionClass($this->getClassName());
			$properties = $info->getProperties();
			$props_arr = array();
			foreach ($properties as $prop)
			{
				if ($prop->isStatic())
					continue;
				$name = $prop->getName();
				// $prop->
				if (substr($name, 0, 1) == "_")
					continue;
				
				$props_arr[] = $name;
			}
			if (count($props_arr) > 0)
			{
				self::$StorageProperties[$this->getClassName()] = $props_arr;
				return $props_arr;
			}
			else 
				return null;
		}
		else 
			return self::$StorageProperties[$this->getClassName()];
	}
	/**
	 * Gets the list of properties that will be loaded by default when the object is loaded by the storage
	 * If a property is a reference if will be also loaded, the process will be recursive 
	 * If a property is an array/collection it will be loaded, the process will be recursive 
	 *
	 * @return array Array of string
	 */
	public function getDefaultLoadProperties()
	{
		return null;
	}
	/**
	 * Gets the property with the specified name
	 * The storage will always call this function to get a property
	 * 
	 * @param string $name The name of the property
	 */
	public function getProperty($name)
	{
		return $this->{$name};
	}
	/**
	 * Sets the property with the specifed name
	 * The storage will always call this function to set a property
	 *
	 * @param string $name
	 * @param mixed $value
	 */
	public function setProperty($name, $value)
	{
		$this->{$name} = $value;
	}
	/**
	 * Returns true if this QIData object is a scalar value
	 *
	 * @return boolean
	 */
	public function isValue()
	{
		return false;
	}
	
	/**
	 * If it returns true it means that the object has chaged and it can be saved in the database if needed
	 * If a property is specified then it should return if that property has changed
	 *
	 * @return boolean
	 */
	public function hasChanged($property = null)
	{
		return true;
	}
	
	public function get($key)
	{
		if (isset($this->{$key}))
			return $this->{$key};
		else 
			return null;
	}
	
	public function set($key, $value)
	{
		$this->{$key} = $value;
	}
	
	public function setFromArray($array)
	{
		foreach ($array as $key => $value)
			$this->{$key} = $value;
	}
	
	public static function FromArray($array)
	{
		$o = new QData();
		$o->setFromArray($array);
		return $o;
	}
}

?>